#ifndef _ARBRE
#define _ARBRE

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<string>

#include "noeud.hpp"
#include "parser.hpp"

using namespace std;

struct arbre {
    noeud* racine;
};

/*
    Pour toutes ces fonctions, la variable verbose permet d'afficher des information supplémentaires
    lors de l'éxecution, principalement utiles au débuggage
*/


void initArbre(arbre &a, bool verbose = false);
/* initialise un arbre vide */

void initArbre(arbre &a, int entier, bool verbose = false);
/* initialise un arbre avec un entier */

void initArbre(arbre &a, const arbre &b, bool verbose = false);
/* initialisation par copie d'un arbre
    précondition :  a non initialisé
                    b initialisé
    postcondition : a copie de b (emplacements mémoire distinctifs) */

void initArbre(arbre &a, const noeud &n, bool verbose = false);
/* initialisation par copie d'un noeud
    précondition :  a non initialisé
                    n initialisé
    postcondition : racine de a copie de n (emplacements mémoire distinctifs) */

void initArbre(arbre &a, string expression, bool verbose = false);
/* initialisation par expression
    précondition :  a non initialisé
                    expression une chaine sous forme d'expression polonaise inversée
    postcondition : a initialisé avec l'expression */

void addArbre(const arbre &a, const arbre &b, arbre &resultat, bool verbose = false, bool affComplet = false);
/* préconditions :
    - a et b sont des arbres initialisés et manipulées avec les fonctions du module d'arbre. a et b peuvent êtres vides
    - resultat est un arbre initialisé et vide
    - verbose permet d'afficher les détails d'execution
    - affComplet permet d'afficher les détails des noeuds créés

   postconditions :
    - resultat est un arbre dont le premier noeud contient un + et ces fils contienent les arbres a et b
    - si a ou b est vide, resultat sera copié selon l'arbre non vide
    - si a et b sont vide, resultat sera vide
*/

void multArbre(const arbre &a, const arbre &b, arbre &resultat, bool verbose = false, bool affComplet = false);
/* préconditions :
    - a et b sont des arbres initialisés et manipulées avec les fonctions du module d'arbre. a et b peuvent êtres vides
    - resultat est un arbre initialisé et vide
    - verbose permet d'afficher les détails d'execution
    - affComplet permet d'afficher les détails des noeuds créés

   postconditions :
    - resultat est un arbre dont le premier noeud contient un * et ces fils contienent les arbres a et b
    - si a ou b est vide, resultat sera copié selon l'arbre non vide
    - si a et b sont vide, resultat sera vide
*/

int valeurArbre(const arbre &a);
/*  précondition :  a initialisé
    postcondition : renvoie la valeur arithmétique de l'arbre */

void affichageArbreExpression(const arbre& a);
/*  affiche l'arbre sous forme d'expression
    précondition :  a initialisé  */

void affichageArbreHorizontal(const arbre& a);
/*  affiche l'arbre sous forme horizontale
    précondition :  a initialisé  */

void developpeProduitArbre (const arbre &donne, arbre &dev, bool verbose = false);
/*  devellope le produit d'un abre
    précondition :  donne initialisé
                    dev initialisé
    postcondition : si donne peut être developpé, dev deviens sa forme developpée (emplacements mémoire distinctifs)
                    si donne ne peut être developpé, dev est renvoyé vide */

noeud* racine(const arbre &a);
/*  renvoie la racine de a
    précondition :  a initialisé
    postcondition :   retourne un pointeur sur la racine de a */

bool arbreVide(const arbre &a);
/*  teste si l'arbre est vide
    précondition :  a initialisé
    postcondition :   renvoie vrai si a est vide, faux sinon */

bool arbreFeuille(const arbre &a);
/*  teste si l'arbre est une feuille (aka sa racine n'a pas de fils)
    précondition :  a initialisé et non vide
    postcondition :  renvoie vrai si a est une feuille, faux sinon */

void testamentArbre(arbre &a, bool verbose = false);
/*  libére un arbre
    précondition :  a initialisé
    postcondition : a est libéré*/

#endif
